/*
 * app_system.c
 *
 *  Created on: 17 Aug 2021
 *      Author: NingTao.Huang
 */
#include "driver_Mobvoi_includes.h"
#include "app_Mobvoi_includes.h"
#include "Mobvoi_external.h"
#include "m510t_driver.h"

extern t_scanEnable LMscan_Read_Scan_Enable(void);

static APP_SYSTEM_T g_sys_app;

__inline app_handle_t app_get_sys_handler(void)
{
    return &g_sys_app;
}

jtask_h app_get_audio_task_handle(void)
{
    return g_sys_app.app_audio_task;
}

jtask_h app_common_get_task_handle(void)
{
    return g_sys_app.app_common_task;
}

void delay_us(volatile unsigned long num)
{

    volatile unsigned int i, j, us_count;
    /****
    if (g_Mobvoi_initial_config.cur_cpu_clk == CPU_26M_CLK)
    {
        us_count = 4;
    }
    else
    {
        us_count = 8;
    }
****/
    us_count = 4;
    for (i = 0; i < num; i++)
        for (j = 0; j < us_count; j++)
            ;
}

void app_sleep_func(int enable)
{

    CLEAR_SLEEP_TICK;

#if (CONFIG_DAC_CLOSE_IN_IDLE == 0)
    if ((!app_bt_flag1_get(APP_AUDIO_WORKING_FLAG_SET)))
    {
        aud_dac_close();
    }
#endif

#ifdef CONFIG_APP_USB_DISK
    if (app_is_udisk_mode())
    {
        return;
    }
#endif

#ifdef CONFIG_APP_SDCARD
//    if(app_is_sdcard_mode())
//    {
//        return;
//    }
#endif

    if (enable && (app_bt_flag1_get(APP_FLAG_DUT_MODE_ENABLE | APP_FLAG_LINEIN) || app_wave_playing()))
    {
        return;
    }

#if (CONFIG_DRIVER_OTA == 1)
    if (driver_ota_is_ongoing())
    {
        return;
    }
#endif

#if 0 // CONFIG_CRTL_POWER_IN_BT_SNIFF_MODE  , enter sniff in sniff procedure
    uint8_t idx = 0;
    if(bt_app_check_all_entity_connect_flag(BT_CONNECT_STATE_CONN_PENDING)&&CONFIG_AS_SLAVE_ROLE)
    {
        return;
    }
    if(enable && (hfp_has_connection() || avrcp_has_connection() || a2dp_has_connection())
		&&(app_env_check_sniff_mode_Enable())
		&& (!app_bt_flag1_get(APP_FLAG_RECONNCTION|APP_FLAG_AUTO_CONNECTION)) )
    {
        for(idx=0;idx<NEED_SNIFF_DEVICE_COUNT;idx++)
        {
            btaddr_t raddr = bt_sniff_get_rtaddr_from_idx(idx);
            if(bt_sniff_is_used(idx))
            {
                if(hfp_has_the_sco(raddr)
                    || a2dp_has_the_music(&raddr) )
                {
                    continue;
                }
                if((a2dp_has_the_connection(&raddr)
                	|| hfp_has_the_connection(raddr)))
                {
                    if(!bt_sniff_is_policy(idx))
                    {
                        app_bt_write_sniff_link_policy(bt_sniff_get_handle_from_idx(idx), 1);
                    }
                    else if(bt_sniff_is_active(idx))
                    {
                        os_printf("app_sleep_func\r\n");
                        app_bt_enter_sniff_mode(bt_sniff_get_handle_from_idx(idx), 1);
                    }
                }
            }
        }
    }
#endif
    if (enable)
    {
        if (app_wave_playing())
        {
            app_wave_file_play_stop();
        }
    }
}

uint8_t app_get_best_offset_level(void)
{
    app_env_handle_t env_h = app_env_get_handle();
    if (0x80 == (env_h->env_data.offset_bak_8852 & 0xc0))
        return 3;
    if (0x80 == (env_h->env_data.offset_bak_tester & 0xc0))
        return 2;
    if (0x80 == (env_h->env_data.offset_bak_phone & 0xc0))
        return 1;
    return 0;
}

uint8_t app_get_best_offset(void)
{
    app_env_handle_t env_h = app_env_get_handle();
    uint8 offset = env_h->env_cfg.system_para.frq_offset; //from configer
    //{b7:b6} = 11(no data) 10(have data) 00(not use)
    if (0x80 == (env_h->env_data.offset_bak_phone & 0xc0))
        offset = env_h->env_data.offset_bak_phone;
    if (0x80 == (env_h->env_data.offset_bak_tester & 0xc0))
        offset = env_h->env_data.offset_bak_tester;
    if (0x80 == (env_h->env_data.offset_bak_8852 & 0xc0))
        offset = env_h->env_data.offset_bak_8852;
    return offset & 0x3f;
}

void app_bt_flag1_set(uint32_t flag, uint8_t oper)
{
    app_handle_t sys_hdl;
    uint32_t interrupts_info, mask;

    sys_hdl = app_get_sys_handler();

    SYSirq_Disable_Interrupts_Save_Flags(&interrupts_info, &mask);
    if (oper == 1)
    {
        sys_hdl->flag_sm1 |= flag;
    }
    else if (oper == 0)
    {
        sys_hdl->flag_sm1 &= ~flag;
    }
    SYSirq_Interrupts_Restore_Flags(interrupts_info, mask);

    return;
}

int app_bt_flag1_get(uint32_t flag)
{
    app_handle_t sys_hdl = app_get_sys_handler();

    return (sys_hdl->flag_sm1 & flag);
}

void app_bt_flag2_set(uint32_t flag, uint8_t oper)
{
    app_handle_t sys_hdl;
    uint32_t interrupts_info, mask;

    sys_hdl = app_get_sys_handler();

    SYSirq_Disable_Interrupts_Save_Flags(&interrupts_info, &mask);
    if (oper == 1)
    {
        sys_hdl->flag_sm2 |= flag;
    }
    else if (oper == 0)
    {
        sys_hdl->flag_sm2 &= ~flag;
    }
    SYSirq_Interrupts_Restore_Flags(interrupts_info, mask);

    return;
}

int app_bt_flag2_get(uint32_t flag)
{
    app_handle_t sys_hdl = app_get_sys_handler();

    return (sys_hdl->flag_sm2 & flag);
}

__INLINE__ uint8_t app_led_is_pairing(void)
{
    app_handle_t app_h = app_get_sys_handler();
    APP_LED_EVENT event = app_h->led_event;
    uint8_t scan_status = (uint8_t)LMscan_Read_Scan_Enable();

    if ((((event == LED_EVENT_MATCH_STATE) && (scan_status == BOTH_SCANS_ENABLED)) || ((event == LED_EVENT_NO_MATCH_NO_CONN_STATE) && (scan_status == NO_SCANS_ENABLED))) && ((app_h->led_info[event].led_ontime != 0) || (app_h->led_info[event].led_offtime != 0)))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

int8_t app_is_available_sleep_system(void)
{
#if CONFIG_CRTL_POWER_IN_BT_SNIFF_MODE
    if (!app_env_check_sniff_mode_Enable())
        return 0;

    return !(app_bt_flag1_get(APP_CPU_NOT_HALT_FLAG_SET) || bt_connection_active() || saradc_get_chnl_busy() || bt_app_check_all_entity_connect_flag(BT_CONNECT_STATE_RECONNECTING) || bt_app_check_all_entity_connect_flag(BT_CONNECT_STATE_RECONN_FAILED) || app_bt_flag2_get(APP_FLAG2_WAKEUP_DLY) || app_bt_flag2_get(APP_FLAG2_HFP_INCOMING) || vusb_get_mode() || get_Charge_state() || app_led_is_pairing()
#if CONFIG_ANC_ENABLE
             || app_anc_status_get()
#endif
    );
#else
    return 0;
#endif
}

void app_low_power_scanning(uint32_t step)
{
    app_handle_t app_h = app_get_sys_handler();
    app_env_handle_t env_h = app_env_get_handle();

    /**************** Battery level detect ******************/
    app_h->low_detect_count += step;
    if ((app_h->low_detect_count >= 200) // Min:>2s
        && (app_h->low_detect_count >= env_h->env_cfg.system_para.lp_interval >> 2) && !app_wave_playing())
    {
        app_h->low_detect_count = 0;
#if (CONFIG_TEMPERATURE_NTC == 1)
        if (app_charge_is_powerdown())
        {
            msg_put(MSG_TEMPRATURE_NTC_DETECT);
        }
        else
#endif
        {
            msg_put(MSG_LOWPOWER_DETECT);
        }
    }
}

void app_temprature_scanning()
{
    static uint64_t s_temperature_timer_cnt = 0;
    uint64_t t1;

    t1 = os_get_tick_counter();
    if ((t1 - s_temperature_timer_cnt) >= 1000) // 10s
    {
        s_temperature_timer_cnt = t1;
        msg_put(MSG_TEMPERATURE_DETECT);
    }
}

//void set_iphone_bat_level_result(void)
//{
//    app_handle_t app_h = app_get_sys_handler();
//    app_h->iphone_bat_lever_bak = app_h->iphone_bat_lever;
//}

void app_low_power_detect(void)
{
    app_handle_t app_h = app_get_sys_handler();
    uint8_t lowpower_flag = 0;
    //return;
    //app_sleep_func(0);

    if (saradc_get_chnl_busy() || app_bt_flag1_get(APP_FLAG_POWERDOWN) || (app_charge_is_usb_plug_in() == 1))
        return;

    //app_sleep_func(0);
    if (app_env_check_bat_display())
    {
#if (CONFIG_BLUETOOTH_EN == 1)
        if (hfp_has_connection())
        {
            app_h->iphone_bat_lever = set_iphone_bat_lever();
            if (app_h->iphone_bat_lever != app_h->iphone_bat_lever_bak)
            {
                //if we don't rev AT_RESULT_OK, send it three times per 2s
                //if (++iphone_bat_lever_bak_cnt >= 3)
                {
                    //app_h->iphone_bat_lever_bak_cnt = 0;
                    app_h->iphone_bat_lever_bak = app_h->iphone_bat_lever;
                }
                //os_printf("iphone_bat_lever:%d\r\n",iphone_bat_lever);
                hf_cmd_set_iphone_batlevel(app_h->iphone_bat_lever);
            }
        }
#endif
    }

    lowpower_flag = saradc_lowpower_status();
    //os_printf("lf:%d,adc:%d,mv:%d\r\n",lowpower_flag,saradc_get_value(),((saradc_get_value()*4600)>>10));
    if (!app_bt_flag1_get(APP_FLAG_LOWPOWER) && lowpower_flag)
    {
        app_bt_flag1_set(APP_FLAG_LOWPOWER, 1);
        //os_printf("step1\n");
        if (app_get_led_low_battery_index() == LED_EVENT_END)
        {
            //os_printf("step2\n");
            //app_set_led_event_action(LED_EVENT_LOW_BATTERY);
            button_set_led(M510T_LED_LOW_POWER);
            app_bt_flag2_set(APP_FLAG2_LED_LOWPOWER, 1);
        }
        else if (get_Charge_state() == 0)
        {
            //os_printf("step3\n");
            app_set_led_low_battery_all_in(0);
        }
    }
    else if (app_bt_flag1_get(APP_FLAG_LOWPOWER) && saradc_normalpower_status())
    {
        //os_printf("step4\n");
        app_bt_flag1_set(APP_FLAG_LOWPOWER, 0);
        app_bt_flag2_set(APP_FLAG2_LED_LOWPOWER, 0);
        if (get_Charge_state() == 0)
            app_set_led_low_battery_all_in(1);
        app_set_led_event_action(app_h->led_event_save);
    }

    if (app_bt_flag1_get(APP_FLAG_LOWPOWER))
    {
        //os_printf("step5\n");
        if (lowpower_flag == 2)
        {
            lowpower_flag = 0;
            LOG_I(APP, "low power,power down\r\n");
            /*powerdown and disable the saradc*/
            REG_SYSTEM_0x05 |= MSK_SYSTEM_0x05_SADC_PWD;
            start_wave_and_action(APP_WAVE_FILE_ID_POWEROFF, app_powerdown);

            return;
        }

        if (lowpower_flag == 1)
        {
            //os_printf("step6\n");
            if (!app_bt_flag2_get(APP_FLAG2_LED_LOWPOWER) && (app_get_led_low_battery_index() == LED_EVENT_END))
            {
                //os_printf("step7\n");
                app_bt_flag2_set(APP_FLAG2_LED_LOWPOWER, 1);
                button_set_led(M510T_LED_LOW_POWER);
            }
            saradc_reset();
            switch (app_h->sys_work_mode)
            {
#if (CONFIG_APP_MP3PLAYER == 1)
            case SYS_WM_SD_MUSIC_MODE:
                app_playwav_resumeMp3(APP_WAVE_FILE_ID_LOW_BATTERY);
                break;
#endif
            case XZX_S10_LINEIN_MODE:
#if 0//(CONFIG_USE_USB == 0)
                app_playwav_resumelinein(APP_WAVE_FILE_ID_LOW_BATTERY);
#endif
                break;
            case SYS_WM_BT_MODE:
                app_wave_file_play_start(APP_WAVE_FILE_ID_LOW_BATTERY);
                break;

            default:
                break;
            }
            //   LOG_I(APP,"voice play low power!!!,lowpower_flag=%d\r\n",lowpower_flag);
        }
    }
    saradc_init(SARADC_MODE_CONTINUE, app_h->low_detect_channel, 4);
    saradc_set_chnl_busy(1);
}

void app_audio_restore(void)
{
    uint32_t freq;
    uint32_t channel;
    uint32_t vol_s;
    app_handle_t app_h = app_get_sys_handler();

    if (app_bt_flag1_get(APP_FLAG_POWERDOWN | APP_FLAG_WAVE_PLAYING))
        return;
    app_get_wave_info(&freq, &channel, &vol_s);

#if 0//(CONFIG_USE_USB == 0)

    if (app_bt_flag1_get(APP_FLAG_LINEIN))
    {
        //app_handle_t app_h = app_get_sys_handler();
        if (!app_bt_flag2_get(AP_FLAG2_LINEIN_MUTE))
        {
            aud_dac_close();
            linein_audio_open();

            if (AUDIO_VOLUME_MIN == app_h->linein_vol)
                aud_volume_mute(1);
        }

        return;
    }

    else if (app_is_bt_mode())
    {
        if (!a2dp_has_music() && !hfp_has_sco())
        {
            aud_dac_close();
            aud_volume_mute(1);
        }
        else
        {
            /*
            Because both freq and chnanel are parameters of promt wave,this restore is wrong;
            and there are much delay in function aud_dac_config(),ADC isr can't be processed by CPU in time
            so MSG pool will be full,and printf("F").
            */
            /*
            Fixed Bug#1385
            Both freq and chnanel have been saved in function a2dp_audio_restore,
            so these parameters are a2dp config param
            */
            if (a2dp_has_music() && !hfp_has_sco())
            {
                a2dp_audio_action();
            }
            else
            {
                aud_dac_set_volume(vol_s);
            }

            if (vol_s == AUDIO_VOLUME_MIN)
            {
                aud_volume_mute(1);
            }

            if (hfp_has_sco())
            {
                hf_audio_restore();
            }

            if (hfp_has_sco() || app_bt_flag1_get(APP_FLAG_CALL_ESTABLISHED | APP_FLAG_MUSIC_PLAY | APP_BUTTON_FLAG_PLAY_PAUSE))
                aud_PAmute_delay_operation(0);

            if ((app_h->mic_volume_store & 0x80) && hfp_has_sco())
            {
#ifdef CONFIG_DRIVER_ADC
                aud_mic_mute(1);
#endif
            }
        }
    }
#if (CONFIG_APP_MP3PLAYER == 1)
    else if (app_is_mp3_mode())
    {
        if (mp3_need_pause)
            app_player_button_play_pause();
        mp3_need_pause = 0;
    }
#endif

#else

    aud_dac_close();

    aud_dac_set_volume(app_h->usound_vol);
    aud_dac_config(16000, 2, 16);
    aud_dac_open();
#endif //#if (CONFIG_USE_USB == 0)
}
